package com.bw.call.controller;

import com.bw.call.service.LoggingAdvisor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.time.LocalDate;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;


/**
 * @author lemon
 * @version 1.0
 * @description:
 */
@RestController
public class OpenAiController {

    private final ChatClient chatClient;

    public OpenAiController(ChatClient.Builder chatClientBuilder, VectorStore vectorStore, ChatMemory chatMemory) {
        this.chatClient = chatClientBuilder
                .defaultSystem("""
					   你是"医疗"方面客户聊天支持代理，请以友好的方式来回复，
                       你可以通过在线聊天系统与客户互动，在提供了有关病症的信息之前，
                       在询问患者之前，你需要检查消息历史记录以获取此信息。
                       你可以根据患者的病状高效地为患者匹配到相对应领域的医生。
                       在进行挂号和取消挂号之前,如果之前用户没有输入姓名,
                       你必须等待客户输入姓名,之前输入姓名就使用之前的姓名,
                       需要获取医生姓名和患者姓名。
                       取消挂号前根据医生姓名和患者姓名获取挂号状态，不需要显示状态代码。
                       挂号成功提示医生姓名和金额。
                       今天的日期是 {current_date}.
					""")
                .defaultAdvisors(
                        new PromptChatMemoryAdvisor(chatMemory),
                        new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()), // RAG
                        new LoggingAdvisor())
                .defaultFunctions("getDoctors", "register","cancelRegister","getRegisterData") // FUNCTION CALLING
                .build();
    }

    @GetMapping(value = "/ai/generateStreamAsString", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> generateStreamAsString(@RequestParam(value = "message", defaultValue = "讲个笑话") String message) {
        Flux<String> content = chatClient.prompt()
                .system(s -> s.param("current_date", LocalDate.now().toString()))
                .advisors(a -> a.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100))
                .user(message)
                .stream()
                .content();        return  content
                .concatWith(Flux.just("[complete]"));
    }
}

